﻿#include<iostream>
using namespace std;

//class A
//{
//public:
//	static A* HeapA(int a=0)
//	{
//		return new A(a);
//	}
//private:
//	A(int a)
//		:_a(a)
//	{}
//	A& operator=(const A& aa) = delete;
//
//	int _a = 1;
//};
//
//int main()
//{
//	A* ptr = A::HeapA();
//	return 0;
//}
//class A
//{
//public:
//	A(int a = 0):_a(a)
//	{
//
//	}
//
//private:
//	int _a;
//	A(const A& a) = delete;
//	A& operator=(const A& a) = delete;
//	
//};
//
//int main()
//{
//	A aa;
//	A aaa = aa;
//	return 0;
//}

//
//class StackOnly
//{
//public:
//	static StackOnly CreateObj()
//	{
//		return StackOnly();
//	}
//
//	// 禁掉operator new可以把下面用new 调用拷贝构造申请对象给禁掉
//	// StackOnly obj = StackOnly::CreateObj();
//	// StackOnly* ptr3 = new StackOnly(obj);
//	void* operator new(size_t size) = delete;
//	void operator delete(void* p) = delete;
//private:
//	StackOnly()
//		:_a(0)
//	{}
//private:
//	int _a;
//};
//

// 饿汉模式
// 优点：简单
// 缺点：可能会导致进程启动慢，且如果有多个单例类对象实例启动顺序不确定。


/*class Singleton
{
public:
	Singleton* getInstacne()
	{
		return _instance;
	}

private:
	Singleton() {}
	Singleton(const Singleton& s) = delete;
	Singleton& operator=(const Singleton& s) = delete;

	static Singleton* _instance;
};
Singleton* Singleton::_instance = new Singleton();*/


//懒汉模式
//#include<thread>
//#include<mutex>
//class Singleton
//{
//public:
//	static Singleton* getInstance()
//	{
//		if (_instance == nullptr)
//		{
//			mtx.lock();
//			if (_instance == nullptr)
//			{
//				cout << " test " << endl;
//				_instance = new Singleton();
//			}
//			mtx.unlock();
//		}
//		return _instance;
//	}
//
//	class CGarbo//自动回收单例类
//	{
//	public:
//		~CGarbo()
//		{
//			if (Singleton::_instance != nullptr)
//			{
//				delete Singleton::_instance;
//				Singleton::_instance = nullptr;
//			}
//		}
//	};
//	static CGarbo gc;
//private:
//	Singleton() {}
//	Singleton(const Singleton& s) = delete;
//	Singleton operator=(const Singleton& s) = delete;
//
//	static Singleton* _instance;
//	static mutex mtx;
//};
//
//Singleton* Singleton::_instance=nullptr;
//mutex Singleton::mtx;
//Singleton::CGarbo Singleton::gc;
//
//
//int main()
//{
//	Singleton* s = Singleton::getInstance();
//	s->gc.~CGarbo();
//	s = Singleton::getInstance();
//	return 0;
//}

#include<mutex>
#include<vector>
class Singleton
{
public:
	static Singleton* GetInstance()
	{
		// 双检查加锁
		if (_ins == nullptr)  // 提高效率
		{
			_imtx.lock();

			if (_ins == nullptr)  // 线程安全
			{
				_ins = new Singleton;
			}

			_imtx.unlock();
		}

		return _ins;
	}

	// 一般全局都要使用单例对象，所以单例对象一般不需要显示释放
	// 有些特殊场景，想显示释放一下
	static void DelInstance()
	{
		_imtx.lock();
		if (_ins)
		{
			delete _ins;
			_ins = nullptr;
		}
		_imtx.unlock();
	}

	// 内部类：单例对象回收
	class GC
	{
	public:
		~GC()
		{
			DelInstance();
		}
	};

	static GC _gc;

	void Add(const string& str)
	{
		_vmtx.lock();

		_v.push_back(str);

		_vmtx.unlock();
	}

	void Print()
	{
		_vmtx.lock();

		for (auto& e : _v)
		{
			cout << e << endl;
		}
		cout << endl;

		_vmtx.unlock();
	}

	~Singleton()
	{
		// 持久化
		// 比如要求程序结束时，将数据写到文件，单例对象析构时持久化就比较好
	}

private:
	// 限制类外面随意创建对象
	Singleton()
	{}

	// 防拷贝
	Singleton(const Singleton& s) = delete;
	Singleton& operator=(const Singleton& s) = delete;

private:
	mutex _vmtx;
	vector<string> _v;

	static Singleton* _ins;
	static mutex _imtx;
};

Singleton* Singleton::_ins = nullptr;
mutex Singleton::_imtx;

Singleton::GC Singleton::_gc;
